package com.fintech.pangu.commons.jwt;

import com.alibaba.fastjson.JSON;
import com.fintech.pangu.commons.model.UserDetail;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.SignatureException;
import io.jsonwebtoken.UnsupportedJwtException;
import io.jsonwebtoken.impl.TextCodec;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

@Slf4j
public class JWTUtil {


    /**
     * 生成JWT
     * @param userName
     * @param jwtSecret
     * @param jwtExpirationInMs
     * @param claims
     * @return
     */
    public static String generateToken(String userName, String jwtSecret, int jwtExpirationInMs, Map<String, Object> claims) {
        // TODO 校验参数


        JwtBuilder jwtBuilder = Jwts.builder();

        // Subject - JWT面向的用户
        jwtBuilder.setSubject(userName);
        jwtBuilder.claim("userName", userName);

        // IssuedAt - 签发时间
        jwtBuilder.setIssuedAt(new Date());

        // Expiration - 过期时间
        if(jwtExpirationInMs != -1){
            Date now = new Date();
            Date expiryDate = new Date(now.getTime() + jwtExpirationInMs);
            jwtBuilder.setExpiration(expiryDate);
        }

        // Claims
        if(claims!=null && !claims.keySet().isEmpty()){
            Set keySet = claims.keySet();
            Iterator iterator = keySet.iterator();
            while(iterator.hasNext()){
                String chaimName = (String)iterator.next();
                Object value = claims.get(chaimName);

                jwtBuilder.claim(chaimName, value);
            }
        }

        jwtBuilder.signWith(SignatureAlgorithm.HS512, TextCodec.BASE64.encode(jwtSecret));

        return jwtBuilder.compact();
    }

    /**
     * 根据JWT获取用户名username
     * @param jwt
     * @param jwtSecret
     * @return
     */
    public static String getUserNameFromJWT(String jwt, String jwtSecret) {
        Claims claims = Jwts.parser()
                .setSigningKey(TextCodec.BASE64.encode(jwtSecret))
                .parseClaimsJws(jwt)
                .getBody();

        return claims.get("userName", String.class);
    }

    public static UserDetail getUserInfoFromJWT(String jwt, String jwtSecret) {
        UserDetail user = null;

        if (StringUtils.isEmpty(jwt)) {
            return user;
        }

        Claims claims = Jwts.parser()
                .setSigningKey(TextCodec.BASE64.encode(jwtSecret))
                .parseClaimsJws(jwt)
                .getBody();
        // 解析
        user = JSON.parseObject(JSON.toJSONString(claims), UserDetail.class);

        return user;
    }



    /**
     * 校验JWT
     * @param jwt
     * @param jwtSecret
     * @return
     */
    public static boolean validateToken(String jwt, String jwtSecret) {
        try {
            Jwts.parser().setSigningKey(TextCodec.BASE64.encode(jwtSecret)).parseClaimsJws(jwt);
            return true;
        }
        catch (SignatureException ex) {
            log.error("Invalid JWT signature");
        }
        catch (MalformedJwtException ex) {
            log.error("Invalid JWT token");
        }
        catch (ExpiredJwtException ex) {
            log.error("Expired JWT token");
        }
        catch (UnsupportedJwtException ex) {
            log.error("Unsupported JWT token");
        }
        catch (IllegalArgumentException ex) {
            log.error("JWT claims string is empty.");
        }

        return false;
    }

}
